/*
 * !!! works on 32bit cpu only !!!
 * # cl private.cpp
 * # g++ private.cpp -o private -rdynamic -ldl
 */
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#define FORCE_EXPORT __declspec(dllexport)
#define FORCE_COMPILE
#endif
#ifdef __linux__
#include <dlfcn.h>
#define FORCE_EXPORT __attribute__((visibility("default")))
#define FORCE_COMPILE __attribute__((used))
#endif

class FORCE_EXPORT A
{
public:
    A(int a) : m_a(a) { }
private:
    static void foo() FORCE_COMPILE { printf("calling private function A::foo()\n"); }
    void bar() FORCE_COMPILE { printf("calling private function A::bar() with %d\n", m_a); }
    int m_a;
};

int main()
{
    typedef void (*FnFoo)();
    typedef void (*FnBar)(A *);
    A a(10);
#ifdef _WIN32
    HMODULE handle = GetModuleHandle(NULL);
    FnFoo fn = (FnFoo)GetProcAddress(handle, "?foo@A@@CAXXZ");
    FnBar fn2 = (FnBar)GetProcAddress(handle, "?bar@A@@AAEXXZ");
    fn();
    /* this pointer is passed in ecx for msvc. */
    __asm {
        lea ecx, a;
        call fn2;
    }
#endif
#ifdef __linux__
    void *handle = dlopen(NULL, RTLD_LAZY);
    FnFoo fn = (FnFoo)dlsym(handle, "_ZN1A3fooEv");
    FnBar fn2 = (FnBar)dlsym(handle, "_ZN1A3barEv");
    fn();
    fn2(&a);
    dlclose(handle);
#endif
    return 0;
}

